/**
 * 分支树可视化组件
 * 用于展示项目分支的树形结构
 */
 
// 使用统一配置入口导入所需模块
const { branchService } = require('../../config/services_config');

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 项目ID
    projectId: {
      type: String,
      value: '',
      observer: 'onProjectIdChanged'
    },
    // 当前选中的分支ID
    currentBranchId: {
      type: String,
      value: '',
      observer: 'onCurrentBranchChanged'
    },
    // 图表宽度
    width: {
      type: Number,
      value: 600
    },
    // 图表高度
    height: {
      type: Number,
      value: 400
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    branches: [], // 分支列表
    treeData: { nodes: [], links: [] }, // 树形结构数据
    loading: false, // 加载状态
    error: '', // 错误信息
    canvasContext: null, // 画布上下文
    canvasId: 'branch-tree-canvas' // 画布ID
  },

  /**
   * 组件的生命周期
   */
  lifetimes: {
    attached() {
      // 如果有项目ID，加载分支数据
      if (this.properties.projectId) {
        this.loadBranchData();
      }
    },
    
    ready() {
      // 初始化画布
      this.initCanvas();
    },
    
    detached() {
      // 清理资源
      this.data.canvasContext = null;
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 当项目ID变更时触发
     */
    onProjectIdChanged(newVal, oldVal) {
      if (newVal && newVal !== oldVal) {
        this.loadBranchData();
      }
    },
    
    /**
     * 当当前分支ID变更时触发
     */
    onCurrentBranchChanged(newVal, oldVal) {
      if (newVal !== oldVal && this.data.treeData) {
        this.renderTree();
      }
    },
    
    /**
     * 加载分支数据
     */
    async loadBranchData() {
      const projectId = this.properties.projectId;
      if (!projectId) return;

      this.setData({
        loading: true,
        error: ''
      });

      try {
        // 获取分支列表
        const branches = await branchService.getBranchList(projectId);
        
        // 构建树形结构数据
        const treeData = branchService.buildBranchTree(branches);
        
        // 更新组件数据
        this.setData({
          branches,
          treeData,
          loading: false
        });

        // 渲染树形图
        this.renderTree();

      } catch (error) {
        console.error('[分支树] 加载分支数据出错:', error);
        this.setData({
          loading: false,
          error: '加载分支数据失败: ' + error.message
        });
      }
    },
    
    /**
     * 初始化画布
     */
    initCanvas() {
      const query = this.createSelectorQuery();
      query.select('#' + this.data.canvasId)
        .fields({ node: true, size: true })
        .exec((res) => {
          if (!res[0]) return;
          
          const canvas = res[0].node;
          const ctx = canvas.getContext('2d');
          
          // 设置画布大小
          const dpr = wx.getSystemInfoSync().pixelRatio;
          canvas.width = res[0].width * dpr;
          canvas.height = res[0].height * dpr;
          ctx.scale(dpr, dpr);
          
          // 保存画布上下文
          this.setData({
            canvasContext: ctx
          }, () => {
            // 渲染树形图
            this.renderTree();
          });
        });
    },
    
    /**
     * 渲染树形图
     */
    renderTree() {
      const { canvasContext: ctx, treeData } = this.data;
      const { width, height } = this.properties;
      
      if (!ctx || !treeData || !treeData.nodes || treeData.nodes.length === 0) return;
      
      // 清空画布
      ctx.clearRect(0, 0, width, height);
      
      // 计算节点位置
      const nodePositions = this.calculateNodePositions(treeData);
      
      // 绘制连接线
      this.drawLinks(ctx, treeData.links, nodePositions);
      
      // 绘制节点
      this.drawNodes(ctx, treeData.nodes, nodePositions);
      
      // 触发渲染完成事件
      this.triggerEvent('renderComplete', {
        treeData,
        nodePositions
      });
    },
    
    /**
     * 计算节点位置
     */
    calculateNodePositions(treeData) {
      const { nodes, links } = treeData;
      const { width, height } = this.properties;
      
      // 简单布局算法：水平分层
      const nodeMap = new Map();
      const layers = []; // 每一层的节点
      
      // 查找根节点（没有入边的节点）
      const rootNodes = nodes.filter(node => {
        return !links.some(link => link.target === node.id);
      });
      
      // 如果没有根节点，使用第一个节点作为根节点
      if (rootNodes.length === 0 && nodes.length > 0) {
        rootNodes.push(nodes[0]);
      }
      
      // 构建层级
      const buildLayers = (nodeIds, layerIndex) => {
        if (layerIndex >= 10) return; // 防止无限递归
        
        if (!layers[layerIndex]) {
          layers[layerIndex] = [];
        }
        
        nodeIds.forEach(nodeId => {
          const node = nodes.find(n => n.id === nodeId);
          if (!node) return;
          
          // 将节点添加到当前层
          if (!layers[layerIndex].includes(nodeId)) {
            layers[layerIndex].push(nodeId);
          }
          
          // 查找子节点
          const childLinks = links.filter(link => link.source === nodeId);
          const childNodeIds = childLinks.map(link => link.target);
          
          if (childNodeIds.length > 0) {
            buildLayers(childNodeIds, layerIndex + 1);
          }
        });
      };
      
      // 从根节点开始构建层级
      buildLayers(rootNodes.map(node => node.id), 0);
      
      // 计算每个节点的位置
      const nodePositions = {};
      const NODE_WIDTH = 120;
      const NODE_HEIGHT = 40;
      const HORIZONTAL_SPACING = 50;
      const VERTICAL_SPACING = 80;
      
      layers.forEach((layerNodeIds, layerIndex) => {
        const layerY = 50 + layerIndex * (NODE_HEIGHT + VERTICAL_SPACING);
        const totalLayerWidth = layerNodeIds.length * NODE_WIDTH + (layerNodeIds.length - 1) * HORIZONTAL_SPACING;
        const layerStartX = (width - totalLayerWidth) / 2;
        
        layerNodeIds.forEach((nodeId, nodeIndex) => {
          const nodeX = layerStartX + nodeIndex * (NODE_WIDTH + HORIZONTAL_SPACING);
          nodePositions[nodeId] = {
            x: nodeX,
            y: layerY,
            width: NODE_WIDTH,
            height: NODE_HEIGHT
          };
        });
      });
      
      return nodePositions;
    },
    
    /**
     * 绘制连接线
     */
    drawLinks(ctx, links, nodePositions) {
      links.forEach(link => {
        const sourcePos = nodePositions[link.source];
        const targetPos = nodePositions[link.target];
        
        if (!sourcePos || !targetPos) return;
        
        // 设置线条样式
        ctx.lineWidth = 2;
        
        // 根据合并状态设置颜色
        switch (link.mergeStatus) {
          case 'merged':
            ctx.strokeStyle = '#67C23A'; // 绿色
            break;
          case 'conflict':
            ctx.strokeStyle = '#F56C6C'; // 红色
            break;
          default:
            ctx.strokeStyle = '#909399'; // 灰色
        }
        
        // 绘制折线
        ctx.beginPath();
        ctx.moveTo(sourcePos.x + sourcePos.width / 2, sourcePos.y + sourcePos.height);
        
        // 计算控制点
        const midY = (sourcePos.y + sourcePos.height + targetPos.y) / 2;
        
        // 绘制三段折线
        ctx.lineTo(sourcePos.x + sourcePos.width / 2, midY);
        ctx.lineTo(targetPos.x + targetPos.width / 2, midY);
        ctx.lineTo(targetPos.x + targetPos.width / 2, targetPos.y);
        
        ctx.stroke();
        
        // 绘制箭头
        const arrowSize = 6;
        ctx.beginPath();
        ctx.moveTo(targetPos.x + targetPos.width / 2, targetPos.y);
        ctx.lineTo(targetPos.x + targetPos.width / 2 - arrowSize, targetPos.y - arrowSize);
        ctx.lineTo(targetPos.x + targetPos.width / 2 + arrowSize, targetPos.y - arrowSize);
        ctx.closePath();
        ctx.fillStyle = ctx.strokeStyle;
        ctx.fill();
      });
    },
    
    /**
     * 绘制节点
     */
    drawNodes(ctx, nodes, nodePositions) {
      const { currentBranchId } = this.properties;
      
      nodes.forEach(node => {
        const pos = nodePositions[node.id];
        if (!pos) return;
        
        // 设置节点背景颜色
        const isCurrentBranch = node.id === currentBranchId;
        ctx.fillStyle = isCurrentBranch ? '#409EFF' : (node.isMain ? '#67C23A' : '#f5f7fa');
        
        // 设置阴影
        ctx.shadowColor = 'rgba(0, 0, 0, 0.1)';
        ctx.shadowBlur = 4;
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 2;
        
        // 绘制圆角矩形
        const radius = 6;
        ctx.beginPath();
        ctx.moveTo(pos.x + radius, pos.y);
        ctx.lineTo(pos.x + pos.width - radius, pos.y);
        ctx.quadraticCurveTo(pos.x + pos.width, pos.y, pos.x + pos.width, pos.y + radius);
        ctx.lineTo(pos.x + pos.width, pos.y + pos.height - radius);
        ctx.quadraticCurveTo(pos.x + pos.width, pos.y + pos.height, pos.x + pos.width - radius, pos.y + pos.height);
        ctx.lineTo(pos.x + radius, pos.y + pos.height);
        ctx.quadraticCurveTo(pos.x, pos.y + pos.height, pos.x, pos.y + pos.height - radius);
        ctx.lineTo(pos.x, pos.y + radius);
        ctx.quadraticCurveTo(pos.x, pos.y, pos.x + radius, pos.y);
        ctx.closePath();
        ctx.fill();
        
        // 重置阴影
        ctx.shadowColor = 'transparent';
        
        // 设置文字颜色
        ctx.fillStyle = isCurrentBranch ? '#ffffff' : '#303133';
        ctx.font = '13px sans-serif';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        
        // 绘制分支名称
        ctx.fillText(
          this.truncateText(node.name, pos.width - 20),
          pos.x + pos.width / 2,
          pos.y + pos.height / 2
        );
        
        // 绘制分支类型标记
        if (node.type) {
          const typeColors = {
            feature: '#409EFF',
            bugfix: '#E6A23C',
            release: '#67C23A'
          };
          
          const tagWidth = 10;
          const tagHeight = 10;
          const tagX = pos.x + 8;
          const tagY = pos.y + 8;
          
          ctx.fillStyle = typeColors[node.type] || '#909399';
          ctx.beginPath();
          ctx.arc(tagX, tagY, tagHeight / 2, 0, Math.PI * 2);
          ctx.fill();
        }
      });
    },
    
    /**
     * 截断文本
     */
    truncateText(text, maxWidth) {
      if (!text) return '';
      
      const { canvasContext: ctx } = this.data;
      if (!ctx) return text;
      
      if (ctx.measureText(text).width <= maxWidth) {
        return text;
      }
      
      let truncated = text;
      while (ctx.measureText(truncated + '...').width > maxWidth) {
        truncated = truncated.slice(0, -1);
        if (truncated.length <= 3) break;
      }
      
      return truncated + '...';
    },
    
    /**
     * 处理画布点击事件
     */
    onCanvasTap(e) {
      const { x, y } = e.detail;
      const { treeData } = this.data;
      
      if (!treeData || !treeData.nodes) return;
      
      // 计算节点位置
      const nodePositions = this.calculateNodePositions(treeData);
      
      // 查找被点击的节点
      for (const node of treeData.nodes) {
        const pos = nodePositions[node.id];
        if (!pos) continue;
        
        if (
          x >= pos.x && x <= pos.x + pos.width &&
          y >= pos.y && y <= pos.y + pos.height
        ) {
          // 触发节点点击事件
          this.triggerEvent('nodeTap', {
            nodeId: node.id,
            node: node
          });
          break;
        }
      }
    },
    
    /**
     * 刷新树形图
     */
    refresh() {
      this.loadBranchData();
    }
  }
}); 